package jmine.tec.services.utils.converter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import jmine.tec.services.api.ServiceExecutionException;
import jmine.tec.services.io.ServicesPageBean;
import jmine.tec.services.io.ServicesReader;
import jmine.tec.services.io.ServicesWriter;

import org.apache.log4j.Logger;

import bancosys.tec.services.input.driver.DigesterDriverServicesReader;
import bancosys.tec.services.input.driver.XLSServiceWriter;
import bancosys.tec.services.input.driver.XMLServiceWriter;

/**
 * Utilitario que se propoe a executar a conversão de servicos em formatos de arquivos diferentes.
 * 
 * @author Rafael Volpato
 * @date Aug 24, 2009
 */
public final class ServicesConverter {

    private static final Logger LOG = Logger.getLogger(ServicesConverter.class);

    private final ServicesReader serviceReader;

    private final ServicesWriter serviceWriter;

    private final String fileExtension;

    /**
     * Main.
     * 
     * @param args args
     * @throws IOException
     * @throws ServiceExecutionException
     */
    public static void main(String[] args) throws ServiceExecutionException, IOException {
        if (args.length < 1) {
            System.out.println("O nome do arquivo ou diretorio a ser convertido deve ser informado");
            System.exit(1);
        }
        String format = System.getProperty("format", "xml"); // -Dformat=xml
        ServicesWriter serviceWriter;
        String fileExtension;
        if ("xls".equalsIgnoreCase(format)) {
            serviceWriter = new XLSServiceWriter();
            fileExtension = "_converted.xls";
        } else {
            serviceWriter = new XMLServiceWriter();
            fileExtension = ".xml";
        }
        ServicesConverter servicesConverter = new ServicesConverter(serviceWriter, fileExtension);
        servicesConverter.convert(args[0]);
    }

    /**
     * Construtor.
     */
    public ServicesConverter(ServicesWriter serviceWriter, String fileExtension) {
        this.serviceReader = new DigesterDriverServicesReader(null, null);
        this.serviceWriter = serviceWriter;
        this.fileExtension = fileExtension;
    }

    public void convert(String fileOrDirectoryLocation) throws ServiceExecutionException, IOException {
        File fileOrDirectory = new File(fileOrDirectoryLocation);
        if (!fileOrDirectory.exists()) {
            throw new RuntimeException("O arquivo '" + fileOrDirectory.getAbsolutePath() + "' não existe!");
        }
        if (!fileOrDirectory.canRead()) {
            throw new RuntimeException("O arquivo '" + fileOrDirectory.getAbsolutePath() + "' não pode ser lido!");
        }

        if (fileOrDirectory.isDirectory()) {
            this.convertDirectory(fileOrDirectory);
        } else if (fileOrDirectory.isFile()) {
            this.convertFile(fileOrDirectory);
        } else {
            throw new RuntimeException("Tipo de arquivo desconhecido: " + fileOrDirectoryLocation);
        }
    }

    private void convertDirectory(File dir) throws MalformedURLException, IOException {
        String regex = System.getProperty("regex", ".*/postscript/.*\\.[Xx]([Ll][Ss]|[Mm][Ll])$");
        for (File listedFile : dir.listFiles()) {
            if (listedFile.getAbsolutePath().contains(".svn") || listedFile.getAbsolutePath().contains("/target/")) {
                continue;
            }

            if (listedFile.isFile() && listedFile.getAbsolutePath().matches(regex)) {
                this.convertFile(listedFile);
            } else if (listedFile.isDirectory()) {
                this.convertDirectory(listedFile);
            } else {
                LOG.warn("Ignorando arquivo " + listedFile.getAbsolutePath());
            }
        }
    }

    private void convertFile(File originalServicesFile) throws MalformedURLException, IOException {
        URL originalServicesURL = originalServicesFile.toURI().toURL();
        if (originalServicesURL == null) {
            throw new RuntimeException("O arquivo '" + originalServicesFile.getAbsolutePath() + "' não pode ser lido (url)!");
        }

        this.convertURL(originalServicesFile, originalServicesURL);
    }

    private void convertURL(File originalFile, URL originalURL) throws IOException {
        String destinationFile = originalFile.getAbsolutePath().replaceAll("\\.[Xx]([Ll][Ss]|[Mm][Ll])$", this.fileExtension);
        OutputStream outputStream = new FileOutputStream(destinationFile);
        try {
            List<ServicesPageBean> servicesPages = this.serviceReader.readServicesPageBean(originalURL.getFile(), originalURL.openStream());
            this.serviceWriter.writeServices(servicesPages, outputStream);
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            outputStream.flush();
            outputStream.close();
        }

        // remover o arquivo original.
        originalFile.deleteOnExit();
    }
}
